using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Audio;

namespace DarwinIsDead.Traits {
    public class SprintTrait : Trait {
        Player player;
        private int healthBonus;
        private float sprintDistance;
		private float walkSpeed;
		private float sprintSpeed;
		private float sprintFrequency;
		private bool isSprinting;
		private float sprintTime;
        private float lastSprintStartTime;
        private float lastSprintEndTime;
        private float currentTime;
        private SpriteFont font;

        private Texture2D sprite;
        private SpriteFont debugFont;
        
        public SprintTrait(Zombie owner, World world=null)
            : base(owner, world) {
        }


        public override void Initialize() {
            // Apply any changes to the owning Zombie that doesn't involve
            // accessing other Traits
            //Owner.HitBox.Width += 64;   // Add some dimension to the zombie's hitbox
            //Owner.HitBox.Height += 64;

            //font = World.Game.Content.Load<SpriteFont>("Fonts\\Courier New");

            // Load sound, graphics, etc.
            //sprite = World.Game.Content.Load<Texture2D>("Sprites\\Traits\\sprLegs");
            //debugFont = World.Game.Content.Load<SpriteFont>("Fonts\\Courier New");
            
            walkSpeed = 3f; // Moves 1 pixel per second
            healthBonus = 30;  // Adds 30 health to this zombie
			sprintDistance = .10f;  // Sprints 10% closer to the player
			sprintSpeed = 75f;   // Sprints at 60 pixels per second
			sprintFrequency = 3f;  // Sprint every 3 seconds


			isSprinting = false;
            lastSprintEndTime = 0;
            currentTime = 0;
		
            Level = 1;

                        List<Entity> players = World.GetEntities<Player>();
            if (players.Count > 0) {
                player = (Player)players[0];
            }
        }


        public override object Clone()
        {
            SprintTrait ret = new SprintTrait(Owner, World);
            return ret;
        }


        protected override void AdjustLevel(int level) {
            // Apply any changes that occur with leveling up.
            walkSpeed = (1f + level*1f);
			
			sprintDistance = (.10f + level*.75f);
			
			if (sprintDistance > .95) {  //  cap of sprinting 95% closer to player
				sprintDistance = .95f;
			}
			
			sprintFrequency = 3f - level*.25f;
			
			if (sprintFrequency < .5)  {  // cap of sprinting every .5 seconds
				sprintFrequency = .5f;
			}
        }

        protected override void InternalUpdate(GameTime gameTime) {
            // Our delta time (time between game updates) in seconds.
            // You can use whatever format you want, but this is my preferred.
            float dt = gameTime.ElapsedGameTime.Milliseconds / 1000f;
            currentTime += dt;

            // Move to player and hug the bastard
            if (player != null) {

                // Get the distance between the zombie and the player
                float dpx = player.Position.X - Owner.Position.X;
                float dpy = player.Position.Y - Owner.Position.Y;
				float dx, dy;

                float direction = (float)Math.Atan2(dpy, dpx);
				float sprintDx = Math.Abs(dpx);
				float sprintDy = Math.Abs(dpy);
				float totalDistance = (float)Math.Sqrt(dpx*dpx + dpy*dpy) * sprintDistance;


                // initilize sprint start and end times
                if (lastSprintEndTime == 0) {
                    lastSprintEndTime = currentTime;
                    lastSprintStartTime = currentTime;
                }				
				

                // walk if the sprint timer hasn't reached it's specified value yet, or if the zombie is in the middle of a sprint
				if (((Math.Abs(currentTime - lastSprintEndTime) < sprintFrequency) && !isSprinting)) {
					dx = walkSpeed * dt * (float)Math.Cos(direction);
					dy = walkSpeed * dt * (float)Math.Sin(direction);
                    sprintTime = totalDistance / sprintSpeed;
                    lastSprintStartTime = currentTime;
                    //Trace.WriteLine("WALKING" + currentTime + "   " + lastSprintEndTime);
				}
				

                // sprint otherwise
				else {
					dx = sprintSpeed * dt * (float)Math.Cos(direction);
					dy = sprintSpeed * dt * (float)Math.Sin(direction);
					isSprinting = true;
                    //Trace.WriteLine("SPRINTING" + currentTime + "   " + lastSprintEndTime);

				}

                // reset the isSprinting flag, and set the end time
                if (currentTime - lastSprintStartTime > sprintTime) {
                    isSprinting = false;
                    lastSprintEndTime = currentTime;
                }

                // Move the zombie
                Owner.Move(dx, dy);


            }
        }

        protected override void InternalDraw(SpriteBatch spriteBatch, Color color) {
            Vector2 drawPosition = new Vector2(Owner.Position.X, Owner.Position.Y);

            // Draw the damn thing

            /*if (isSprinting) {
                spriteBatch.DrawString(font, "Sprinting", drawPosition, color);
            }
            else {
                spriteBatch.DrawString(font, "Walking", drawPosition, color);
            } 
            spriteBatch.Draw(sprite, drawPosition, color); */
        }
    }
}
